<template>
  <div class="container">
    <label v-if="layouts.includes('info')">共 {{ total }} 条</label>
    <dropdown
      v-if="layouts.includes('pages')"
      :selectedValue="pageSize"
      :items="sizes"
      @selected="changePageSize"
    />
    <i
      v-if="layouts.includes('prev')"
      class="mu-icon-left"
      @click="selectNo > 1 && goto(selectNo - 1)"
      :disabled="selectNo === 1"
    ></i>
    <span
      @click="goto(item.pageNo)"
      v-for="(item, index) in pageNumbers"
      :key="index"
      :class="{
        'mu-icon-more': item.more,
        background,
        'background-selected': background && selectNo === item.pageNo,
        selected: !background && selectNo === item.pageNo,
      }"
      >{{ item.page ? item.pageNo : "" }}</span
    >
    <i
      class="mu-icon-left right"
      @click="selectNo < pages && goto(selectNo + 1)"
      :disabled="selectNo === pages"
      v-if="layouts.includes('next')"
    ></i>
    <label v-if="layouts.includes('goto')">前往</label>
    <input
      v-if="layouts.includes('goto')"
      type="number"
      @keypress.enter="enterGoto"
      v-model="pageNumber"
    />
    <label v-if="layouts.includes('goto')">页</label>
  </div>
</template>
<script>
import dropdown from "../dropdown/index.vue";

function converToItems(arr) {
  return arr.map((c) => {
    return { value: c, name: `${c}条 / 页` };
  });
}

export default {
  name: "mu-pagination",
  data() {
    return {
      pageNumber: "", //输入的页码
      sizes: converToItems([[10, 20, 30, 50, 70, 100]]),
      pageNumbers: [], //页码列表
      pages: 0, //总页数
      selectNo: this.pageIndex, //选中的页码
      _pageSize: 0, //每页显示条数
    };
  },
  components: {
    dropdown,
  },
  created() {
    if (this.pageSizes.length) {
      this._pageSize = this.pageSizes.some((c) => c === this.pageSize)
        ? this.pageSize
        : this.pageSizes[0];
      this.sizes = converToItems(this.pageSizes);
    }
    this.calc();
  },
  methods: {
    //更改每页显示条数
    changePageSize(obj) {
      this.$emit("update:pageSize", obj.value);
      this._pageSize = obj.value;
      this.calc();
      this.trigger();
    },
    //回车跳转
    enterGoto(e) {
      const number = Math.min(
        this.pages,
        Math.max(parseInt(this.pageNumber), 1)
      );
      number !== this.selectNo &&
        (this.selectNo = number) &&
        (this.calc() || this.trigger());
      this.pageNumber = "";
    },
    //跳转
    goto(pageNo) {
      this.selectNo = pageNo;
      this.calc();
      this.trigger();
    },
    //触发事件
    trigger() {
      this.$emit("changed", this.selectNo, this._pageSize);
    },
    //计算
    calc() {
      this.$emit("update:pageIndex", this.selectNo);
      this.pages = Math.ceil(this.total / this._pageSize); //总页码除以每页显示条数=总页数
      this.pageNumbers.splice(0); //先初始化一下总页码
      if (this.pages < 1) {
        //如果总页数小于1的话就没必要继续了
        return;
      }
      const tempPages = [
        {
          page: true,
          pageNo: 1,
        },
      ]; //临时存放页数
      this.selectNo = Math.min(this.selectNo, this.pages);
      if (this.pages > 2) {
        let showPages = Math.min(this.showPages - 2, this.pages - 2); //中间要显示的实际页码总数
        let middle = parseInt(showPages / 2); //中间要显示的页码总数的一半，因为左右要各取一半的值
        let start = Math.max(this.selectNo - middle, 2); //用来生成页码的开始数，但是要考虑不能超过总页码数，所以用math取最大值
        let end = Math.min(this.selectNo + middle, this.pages - 1); //同上，反向相反
        let cha = showPages - (end - start + 1); //差值
        if (start === 2) {
          end += cha;
        } else {
          start -= cha;
        }
        if (start > 2) {
          tempPages.push({ more: true, pageNo: start - 1 });
        }
        while (start > 0 && start <= end) {
          tempPages.push({
            page: true,
            pageNo: start++,
          });
        }
        if (end < this.pages - 1) {
          tempPages.push({
            pageNo: end + 1,
            more: true,
          });
        }
      }
      if (this.pages > 1) {
        tempPages.push({
          page: true,
          pageNo: this.pages,
        });
      }
      this.pageNumbers.push(...tempPages);
    },
  },
  watch: {
    //总条数
    total() {
      this.calc();
    },
    //改变页码
    pageIndex(value) {
      this.calc();
    },
    //每页显示条数
    pageSize(value) {
      this.calc();
    },
  },
  props: {
    //每页显示条数下拉框选项
    pageSizes: {
      type: Array,
      validator(value) {
        return value.length && value.every((c) => !isNaN(c));
      },
    },
    //总条数
    total: {
      required: true,
      type: Number,
      default: 0,
      validator(value) {
        return value > -1;
      },
    },
    //每页显示条数
    pageSize: Number,
    //显示页码数
    showPages: {
      type: Number,
      default: 7,
      validator(value) {
        return value >= 5 && value <= 21 && value % 2 === 1;
      },
    },
    //默认每页显示条数
    defaultPageSize: Number,
    //当前页
    pageIndex: {
      type: Number,
      default: 1,
      validator(value) {
        return value > 0;
      },
    },
    //布局
    layouts: {
      type: Array,
      default() {
        return ["next", "prev", "pages", "goto", "info"];
      },
    },
    //是否有背景色
    background: Boolean,
  },
};
</script>
<style lang="scss" scoped>
@import "../variable.scss";
.container {
  display: flex;
  align-items: center;
  i,
  span {
    cursor: pointer;
  }

  input[type="number"] {
    width: 50px;
    text-align: center;
    display: inline-block;
    height: 25px;
    border: 1px solid #d9dce2;
    outline: none;
    border-radius: 3px;
    transition: 0.2s;
    margin: 0 5px;
    cursor: pointer;
    -moz-appearance: textfield;

    &:hover {
      border-color: #929090;
    }

    &:focus {
      border-color: $blue;
    }

    &::-webkit-inner-spin-button,
    &::-webkit-outer-spin-button {
      -webkit-appearance: none;
      margin: 0;
    }
  }

  .right {
    transform: rotate(180deg);
  }

  @mixin item() {
    height: 30px;
    width: 30px;
    border-radius: 3px;
    text-align: center;
    line-height: 30px;
    margin: 0 5px;
  }

  .selected {
    color: $blue;
    cursor: default;
    &:hover {
      color: $blue;
    }
  }

  .background {
    background: #f3f3f5;
    &:hover {
      color: $blue;
    }

    &-selected {
      background: $blue;
      color: white;
      cursor: default;

      &:hover {
        color: white;
      }
    }
  }

  i[disabled] {
    cursor: not-allowed;
    color: #d3cdcd;
  }

  .dropdownbox {
    margin-top: 3px;
    margin-left: 10px;
  }

  label {
    font-size: 13px;
  }

  i {
    @include item();
  }

  span {
    @include item();
    font-weight: bold;
    font-size: 13px;
  }
}
</style>